`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/04/27 09:03:21
// Design Name: 
// Module Name: IFetc32
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module Ifetc32(
    //Clock and Reset
    input clock,
    input reset,
    //from ALU
    //the calculated address from ALU
    input[31:0] Addr_result,
    //1-->the ALUResult is zero
    input Zero,
    //from Decoder
    //the Address of instruction used by jr
    input[31:0] Read_data_1,
    //from controller
    input Branch, //1-->beq
    input nBranch, //1-->bne
    input Jmp,//1-->j
    input Jal,//1-->jal
    input Jr,//1-->jr

    output[31:0] Instruction,
    //pc+4 to ALU for branch instruction
    output[31:0] branch_base_addr,
    //pc+4 to decoder for jal instruction
    output reg[31:0] link_addr,
    output[31:0] pco

    );
    reg[31:0] PC;
    reg[31:0] Next_PC;
    wire[32:0] PC_plus_4;
    
    
    prgrom instmem(
        .clka(clock),
        .addra(PC[15:2]),
        .douta(Instruction)
    );

    

    assign PC_plus_4[31:2] = PC[31:2] + 1'b1;
    assign PC_plus_4[1:0] = PC[1:0];
    assign branch_base_addr = PC_plus_4[31:0];
    
    assign pco = PC[31:0];

    always @ (*) begin
        if((Branch == 1 && Zero == 1)||(nBranch == 1 && Zero == 0))
            Next_PC = Addr_result;
        else if(Jr == 1)
            Next_PC = Read_data_1;
        else
            Next_PC = PC_plus_4[31:2];

    end

    always @(negedge clock) begin
        if(reset == 1'b1) begin
            PC <= 32'h00000000;
        end
        else if(Jmp == 1'b1) begin
            
            PC <= {4'b0000,Instruction[25:0],2'b00};
            
        end
        else if(Jal == 1'b1) begin
            PC <= {4'b0000,Instruction[25:0],2'b00};
        end
        else PC <= Next_PC << 2;
    end

    always @(posedge Jmp,posedge Jal) begin
        if(Jmp || Jal)
            link_addr <= Next_PC;
        else link_addr <= link_addr;
        
    end



endmodule